package com.game.tank.entity;

import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.ExpireCleanComponent;
import com.almasb.fxgl.dsl.components.KeepOnScreenComponent;
import com.almasb.fxgl.dsl.components.OffscreenCleanComponent;
import com.almasb.fxgl.dsl.components.ProjectileComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import com.almasb.fxgl.texture.AnimatedTexture;
import com.almasb.fxgl.texture.AnimationChannel;
import com.almasb.fxgl.texture.Texture;
import com.game.tank.components.TankComponent;
import com.game.tank.enums.Group;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;

import java.util.List;

/**
 * @author dylovedz
 */
public class GameEntityFactory implements EntityFactory {

    private final double tankSize = 80;

    @Spawns("tank")
    public Entity newTank(SpawnData spawnData) {
        Texture texture = FXGL.texture("tank.png", tankSize, tankSize);
        return FXGL.entityBuilder()
                .type(Group.PLAY)
                .viewWithBBox(texture)
                .with(new KeepOnScreenComponent())
                .with(new TankComponent())
                .collidable()
                .build();
    }

    @Spawns("enemy")
    public Entity newEnemy(SpawnData spawnData) {
        Texture texture = FXGL.texture("tank.png", tankSize, tankSize).multiplyColor(Color.RED);
        Point2D randomPoint = FXGLMath.randomPoint(new Rectangle2D(0, 0, 800 - 60, 600 - 60));
        while (true) {
            List<Entity> entitiesInRange = FXGL.getGameWorld().getEntitiesInRange(new Rectangle2D(randomPoint.getX(), randomPoint.getY(), tankSize, tankSize));

            if (entitiesInRange.isEmpty()) {
                break;
            }
            randomPoint = FXGLMath.randomPoint(new Rectangle2D(0, 0, 800 - 60, 600 - 60));
        }

        return FXGL.entityBuilder()
                .type(Group.ENEMY)
                .at(randomPoint)
                .viewWithBBox(texture)
                .with(new KeepOnScreenComponent())
                .with(new TankComponent())
                .collidable()
                .build();
    }

    @Spawns("bullet")
    public Entity newBullet(SpawnData spawnData) {
        Texture texture = FXGL.texture("bullet.png", 30, 30);
        Point2D point2d = spawnData.get("point2d");
        return FXGL.entityBuilder()
                .type(Group.BULLET)
                .at(spawnData.getX() - texture.getWidth() / 2, spawnData.getY() - texture.getHeight() / 2)
                .viewWithBBox(texture)
                .with(new ProjectileComponent(point2d, 600))
                .with(new OffscreenCleanComponent())
                .collidable()
                .build();
    }

    @Spawns("boom")
    public Entity newBoom(SpawnData spawnData) {
        Image image = FXGL.image("boom.png");
        Duration duration = Duration.seconds(0.35);
        int w = (int) image.getHeight() / 4;
        AnimationChannel animationChannel = new AnimationChannel(image, 1, w, w, duration, 0, 16);
        AnimatedTexture animatedTexture = new AnimatedTexture(animationChannel).play();
        FXGL.play("boom.wav");
        return FXGL.entityBuilder()
                .at(spawnData.getX(), spawnData.getY())
                .view(animatedTexture)
                .with(new ExpireCleanComponent(duration))
                .build();
    }

    @Spawns("wall")
    public Entity newWall(SpawnData spawnData) {
        int width = (int) spawnData.getData().get("width");
        int height = (int) spawnData.getData().get("height");
        return FXGL.entityBuilder()
                .at(spawnData.getX(), spawnData.getY())
                .viewWithBBox(new Rectangle(width, height, Color.TRANSPARENT))
                .build();
    }

    @Spawns("")
    public Entity newEmpty(SpawnData spawnData) {
        return FXGL.entityBuilder()
                .neverUpdated()
                .build();
    }
}
